package ir.blocks;

import ir.Block;
import ir.CellUnit;
import ir.StructuralDefinition;

import java.util.ArrayList;
import java.util.List;

import run.Cell;
import run.Facet;

/**
 * A block representing lists of Units.
 * @author Thomas Chau
 *
 */
public class UnitListsBlk extends Block {

	@Override
	public List<Facet> getLeftFacets(StructuralDefinition d) throws Exception{
		
		// return the left bind-eligible operands
		ArrayList<Facet> realizedUnits = new ArrayList<Facet>();
	
			for (ir.Block b : subblocks) {
				// here, grab facets for this D's cell .. add if not already defined (fn in D);
				List<Facet> leftBindables = b.getLeftFacets(d);
				realizedUnits.addAll(leftBindables);
			}
			
			for (CellUnit c : units) {
				// resolve from the symbol table
				Cell cell = c.getUnderlyingObject(d);
				realizedUnits.addAll(cell.getInFacets());
			}
		
		return realizedUnits;
	}

	@Override
	public List<Facet> getRightFacets(StructuralDefinition d) throws Exception{
		// return the left bind-eligible operands
		ArrayList<Facet> realizedUnits = new ArrayList<Facet>();
		
			for (ir.Block b : subblocks) {
				// here, grab facets for this D's cell .. add if not already defined (fn in D);
				List<Facet> rightBindables = b.getRightFacets(d);
				realizedUnits.addAll(rightBindables);
			}
			
			for (CellUnit c : units) {
				// resolve from the symbol table
				Cell cell = c.getUnderlyingObject(d);
				realizedUnits.addAll(cell.getOutFacets());
			}
//		}
		
		return realizedUnits;
	}
	
	protected UnitBlk getCore() {
		for (Block b : subblocks)
			if (b instanceof UnitBlk)
				return (UnitBlk) b;
		return null;
	}

	// bad hack for AST correction
	public UnitFacetBlk xferUnitFacet() {
		if (type.equals("BLOCK.UNIT_FACET")) {
			// if this is actually a block unit facet,
			// transform all the unit lists blks on the sides into facetblks
			UnitBlk core = null;
			int corePosition = 0 ;
			for (Block b : subblocks) {
				if (b instanceof UnitBlk) {
					core = (UnitBlk) b;
					corePosition = subblocks.indexOf(b);
				}
			}
			UnitFacetBlk replacement = new UnitFacetBlk(core);
			
			// get the facet blocks
			List<String> facetNames = new ArrayList<String>();
			for (ir.Block b : subblocks) {
				// should be a facet block
				if (b instanceof FacetsBlk) {
					if (subblocks.indexOf(b) < corePosition) // left side
						replacement.setLeft((FacetsBlk) b);
					else 
						replacement.setRight((FacetsBlk) b);// right side
				}
				else if (! (b instanceof UnitBlk)) {
					// extract all the facet names from the unitlistsblk and produce a new facetsblk
					UnitListsBlk c = (UnitListsBlk) b;
					FacetsBlk facetBlks = c.getFacetBlks();
					if (subblocks.indexOf(b) < corePosition) // left side
						replacement.setLeft(facetBlks);
					else 
						replacement.setRight(facetBlks);// right side
				}
			}
			
			// now, construct up.
			return replacement;
		}
		return null;
	}

	private FacetsBlk getFacetBlks() {
		for (Block b : subblocks) {
			if (b instanceof FacetsBlk)
				return (FacetsBlk) b;
		}
		return null;
	}
	
	public UnitListsBlk clone() {
		UnitListsBlk replace = new UnitListsBlk();
		for (Block b : subblocks)
			replace.add(b.clone());
		
		for (CellUnit u : units)
			replace.add(u.clone());
		
		replace.setType(type);
		
		return replace;
		
	}
}
